tools/libxc, hvm: Fix 1G page allocation algorithm
authorShan Haitao <haitao.shan@intel.com>
Fri, 28 Jan 2011 11:08:49 +0000 (11:08 +0000)
committerShan Haitao <haitao.shan@intel.com>
Fri, 28 Jan 2011 11:08:49 +0000 (11:08 +0000)
Currently, cur_pages (which is used as index into page_array for
fetching gfns) is used to judge whether it is proper here to allocated
1G pages. However, cur_pages == page_array[cur_pages] only holds true
when it is below 4G. When it is above 4G, page_array[cur_pages] -
cur_pages = 256M.
As a result, when guest has 10G memory, 8 1G-pages are allocated. But
only 2 of them have their corresponding gfns 1G aligned. The other 6
are forced to split to 2M pages, as their starting gfns are 4G+256M,
5G+256M .................

Inside the patch, true gfns are used instead of cur_pages to fix this
issue.

Signed-off-by: Shan Haitao <haitao.shan@intel.com>
Acked-by: George Dunlap <george.dunlap@citrix.com>
tools/libxc/xc_hvm_build.c

index dbac09467cc4feca7a7585b9b897cc73bceee8a7..08bcf3fd18998d79f269712bf5d6ae5a7c039c7a 100644 (file)
@@ -137,7 +137,7 @@ static int setup_guest(xc_interface *xch,
     xen_pfn_t *page_array = NULL;
     unsigned long i, nr_pages = (unsigned long)memsize << (20 - PAGE_SHIFT);
     unsigned long target_pages = (unsigned long)target << (20 - PAGE_SHIFT);
-    unsigned long entry_eip, cur_pages;
+    unsigned long entry_eip, cur_pages, cur_pfn;
     void *hvm_info_page;
     uint32_t *ident_pt;
     struct elf_binary elf;
@@ -215,11 +215,13 @@ static int setup_guest(xc_interface *xch,
 
         if ( count > max_pages )
             count = max_pages;
-        
+
+        cur_pfn = page_array[cur_pages];
+
         /* Take care the corner cases of super page tails */
-        if ( ((cur_pages & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) &&
-             (count > (-cur_pages & (SUPERPAGE_1GB_NR_PFNS-1))) )
-            count = -cur_pages & (SUPERPAGE_1GB_NR_PFNS-1);
+        if ( ((cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) &&
+             (count > (-cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1))) )
+            count = -cur_pfn & (SUPERPAGE_1GB_NR_PFNS-1);
         else if ( ((count & (SUPERPAGE_1GB_NR_PFNS-1)) != 0) &&
                   (count > SUPERPAGE_1GB_NR_PFNS) )
             count &= ~(SUPERPAGE_1GB_NR_PFNS - 1);
@@ -227,9 +229,9 @@ static int setup_guest(xc_interface *xch,
         /* Attemp to allocate 1GB super page. Because in each pass we only
          * allocate at most 1GB, we don't have to clip super page boundaries.
          */
-        if ( ((count | cur_pages) & (SUPERPAGE_1GB_NR_PFNS - 1)) == 0 &&
+        if ( ((count | cur_pfn) & (SUPERPAGE_1GB_NR_PFNS - 1)) == 0 &&
              /* Check if there exists MMIO hole in the 1GB memory range */
-             !check_mmio_hole(cur_pages << PAGE_SHIFT,
+             !check_mmio_hole(cur_pfn << PAGE_SHIFT,
                               SUPERPAGE_1GB_NR_PFNS << PAGE_SHIFT) )
         {
             long done;
@@ -260,15 +262,15 @@ static int setup_guest(xc_interface *xch,
                 count = max_pages;
             
             /* Clip partial superpage extents to superpage boundaries. */
-            if ( ((cur_pages & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) &&
-                 (count > (-cur_pages & (SUPERPAGE_2MB_NR_PFNS-1))) )
-                count = -cur_pages & (SUPERPAGE_2MB_NR_PFNS-1);
+            if ( ((cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) &&
+                 (count > (-cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1))) )
+                count = -cur_pfn & (SUPERPAGE_2MB_NR_PFNS-1);
             else if ( ((count & (SUPERPAGE_2MB_NR_PFNS-1)) != 0) &&
                       (count > SUPERPAGE_2MB_NR_PFNS) )
                 count &= ~(SUPERPAGE_2MB_NR_PFNS - 1); /* clip non-s.p. tail */
 
             /* Attempt to allocate superpage extents. */
-            if ( ((count | cur_pages) & (SUPERPAGE_2MB_NR_PFNS - 1)) == 0 )
+            if ( ((count | cur_pfn) & (SUPERPAGE_2MB_NR_PFNS - 1)) == 0 )
             {
                 long done;
                 unsigned long nr_extents = count >> SUPERPAGE_2MB_SHIFT;